﻿using libemscontrol.act;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

namespace libcontrol
{
    public class PackageParam
    {
        public byte[] ParamData = new byte[255];
        public byte ParamLen;

    }

    public class InterfaceMsgCount
    {
        public byte InterfaceCount;
        public byte MsgCount;
    }

    public struct MCUDATA
    {
        public int SM1POS;
        public int SM2POS;
        public int SM3POS;
        public int SM4POS;

        public int SM5POS;
        public int SM6POS;
        public int SM7POS;
        public int SM8POS;

        public int SM9POS;
        public int SM10POS;
        public int SM11POS;
        public int SM12POS;
    };

    enum STEPSEQ
    {
        STEP_START = 0,
        lSTEP2,
        lSTEP3,
        lSTEP4,
        lSTEP5,
        lSTEP6,
        lSTEP7,
        lSTEP8,
        lSTEP9,
        lSTEP10,
        lSTEP11,
        lSTEP12,
        lSTEP13,
        lSTEP14,
        lSTEP15,
        lSTEP16,
        lSTEP17,
        lSTEP18,
        lSTEP19,
        lSTEP20,
        lSTEP21,
        lSTEP22,
        lSTEP23,
        lSTEP24,
        lSTEP25,
        lSTEP26,
        lSTEP27,
        lSTEP28,
        lSTEP29,
        lSTEP30,

        lSTEP_ERROR6 = 248,
        lSTEP_ERROR5 = 249,
        lSTEP_ERROR4 = 250,
        lSTEP_ERROR3 = 251,
        lSTEP_ERROR2 = 252,
        lSTEP_ERROR1 = 253,
        lSTEP_ERROR = 254,
        lSTEP_OK = 255,
    };

    enum LIB_CALL
    {
        L_NULL,
        RunSM,
        BrakeSM,
        RunAbs,
        GetAbsPos,
        SetAbsOrg,
        DisableSM,
        IsSMStop,
        StopSM,
        GetSMDir,
        SetSMSpeed,

        IsSensorOn,
        IsSensorOff,
        WriteIO,
        NextTo,
        SetActionError,
        IsActionOk,
        IsActionRun,
        SetActionOk,
        SetResult,
        StartAction,
        ExitAction,
        GetParam,
        WaitSMStop,
        WaitSensorOn,
        WaitSensorOff,
        WaitAction,
        JustWaitAction,
        WaitTimeOut,
        WaitRunLength,
        SetErrorInfo,
        SetSubError,
        FindSensor,
        LeaveSensor,
        StartTimer,
        IsTimeOut,
    };
    public class DataPackage
    {
        enum HeadFormmat
        {
         StartPos,
         AddrPos,
         CmdPos,
         LenPos,
        };

        
        byte[] Param = new byte[255];

        byte[] SendDataBuffer = new byte[400];
        byte[] RecvDataBuffer = new byte[400];
        int nRecvLen = 0;
        public byte BoardID;
        public DataPackage()
        {
            SendDataBuffer[(byte)HeadFormmat.StartPos] = 0xfa;
            SendDataBuffer[(byte)HeadFormmat.AddrPos] = 0x30;
        }

       public bool SendDataPackage(byte id,ComCmd Cmd,PackageParam SendParam,PackageParam RecvParam)
        {
            SendDataBuffer[(byte)HeadFormmat.StartPos] = (byte)0xfa;
            SendDataBuffer[(byte)HeadFormmat.CmdPos] = (byte)Cmd;
            SendDataBuffer[(byte)HeadFormmat.AddrPos] = (byte)(0x30 + BoardID);
            SendDataBuffer[(byte)HeadFormmat.LenPos] = SendParam.ParamLen ;
            for(int i=0;i<SendParam.ParamLen;i++)
            {
                SendDataBuffer[(byte)(HeadFormmat.LenPos + i + 1)] = SendParam.ParamData[i];
            }
            byte lrc = 0XFA;
            for(int i=1;i<4+SendParam.ParamLen;i++)
            {
                lrc ^= SendDataBuffer[i];
            }

            SendDataBuffer[4 + SendParam.ParamLen] = lrc;
            string str = "\r\n";
            for (int i = 0; i < SendParam.ParamLen + 5;i++ )
            {
                str += SendDataBuffer[i].ToString("X2") + " ";
            }
            //Logger.WriteDataProtocol("发送数据:"+str);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int nRet = libcom.SendCommand(id, SendDataBuffer, SendParam.ParamLen+5,RecvDataBuffer, ref nRecvLen);
            
            //Logger.WriteDataProtocol("发送数据耗时:"+sw.ElapsedMilliseconds.ToString());
            sw.Stop();
            if (nRet == -1)
            {
                Logger.WriteDataProtocol("发送数据失败");
                return false;
            }

            if (nRet == -2)
            {
                RecvMemData.GetInstance().SendCommErrorMsg();
                return false;
            }
            if (nRet == -3)
            {

                RecvMemData.GetInstance().SendCommErrorMsg();
                return false;

            }

            if(nRet!=1)
            {
                RecvMemData.GetInstance().SendCommErrorMsg();
                return false;
            }

            for(int i=0;i<nRecvLen;i++)
            {
                RecvParam.ParamData[i] = RecvDataBuffer[i];
            }
            RecvParam.ParamLen = (byte)nRecvLen;
            return true;
        }

        public bool SendDataPackage(byte id, ComCmd Cmd,PackageParam RecvParam)
        {
            
            SendDataBuffer[0] = (byte)0xfa;
            SendDataBuffer[2] = (byte)Cmd;
            SendDataBuffer[1] = (byte)(0x30 + BoardID);
            SendDataBuffer[3] = 0;

            byte lrc = 0;
            for (int i = 0; i < 4; i++)
            {
                lrc = (byte)(lrc^SendDataBuffer[i]);
            }
                

            SendDataBuffer[4] = lrc;
          
            int nRet = libcom.SendCommand(id, SendDataBuffer, 5, RecvDataBuffer, ref nRecvLen);
            if (nRet < 0)
            {
                RecvMemData.GetInstance().SendCommErrorMsg();
                return false;
            }


                for (int i = 0; i < nRecvLen; i++)
                {
                    RecvParam.ParamData[i] = RecvDataBuffer[i];
                }

            RecvParam.ParamLen = (byte)nRecvLen;
            return true;
        }

        public bool SendDataPackage(byte id, ComCmd Cmd)
        {
            return true;
        }
    }
    public enum ComType
    {
        Com_Uart,
        Com_Net,
    }

    public class KrBoard
    {
        public byte BoardID;
        public ComType CType = ComType.Com_Uart;
        public byte SlaveID=0;
        DataPackage CommandDataPackage = new DataPackage();
        PackageParam SendCommandParam = new PackageParam();
        public PackageParam RecvCommandParam = new PackageParam();

        public bool DoAction(byte nAction)
        {
            try
            {
                SendCommandParam = new PackageParam();
                SendCommandParam.ParamData[0] = nAction;
                SendCommandParam.ParamLen = 1;
                RecvCommandParam = new PackageParam();
                CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_DO_ACTION, SendCommandParam, RecvCommandParam);
            }
            catch (Exception ex)
            {
                Logger.WriteErrorLog(ex.ToString());
            }

            return true;
        }

        public bool RetryAction(byte nAction)
        {
            try
            {
                SendCommandParam = new PackageParam();
                SendCommandParam.ParamData[0] = nAction;
                SendCommandParam.ParamLen = 1;
                RecvCommandParam = new PackageParam();
                CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_RETRY_CMD, SendCommandParam, RecvCommandParam);
            }
            catch (Exception ex)
            {
                Logger.WriteErrorLog(ex.ToString());
            }

            return true;
        }

        public bool ErrorCanel(byte nAction)
        {
            try
            {
                SendCommandParam = new PackageParam();
                SendCommandParam.ParamData[0] = nAction;
                SendCommandParam.ParamLen = 1;
                RecvCommandParam = new PackageParam();
                CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_ERROR_CANCEL, SendCommandParam, RecvCommandParam);
            }
            catch (Exception ex)
            {
                Logger.WriteErrorLog(ex.ToString());
            }

            return true;
        }


        public InterfaceMsgCount WalkInterfaceMsgCount()
        {
            SendCommandParam.ParamData[0] = 2;
            SendCommandParam.ParamLen = 1;
            RecvCommandParam = new PackageParam();
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_WALK_INTERMSG, SendCommandParam, RecvCommandParam);

            var moduleCountInfo = new InterfaceMsgCount();
            moduleCountInfo.InterfaceCount = RecvCommandParam.ParamData[0];
            moduleCountInfo.MsgCount = RecvCommandParam.ParamData[1];

            return moduleCountInfo;
        }


        public List<InterfaceMsg> GetInterfaceInfo(byte node)
        {
            List<InterfaceMsg> ltRet = new List<InterfaceMsg>();
            SendCommandParam = new PackageParam();
            SendCommandParam.ParamData[0] = 0;
            SendCommandParam.ParamData[1] = node;
            SendCommandParam.ParamLen = 2;
            RecvCommandParam = new PackageParam();
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_WALK_INTERMSG, SendCommandParam, RecvCommandParam);
            byte[] NameBuffer = new byte[30];
            int count = RecvCommandParam.ParamLen / 31;
            int pos;
            Logger.WriteRunLog("此次返回接口数量:" + count);
            for (int i=0;i<count;i++)
            {
                var cinterface = new InterfaceMsg();

                cinterface.ID = RecvCommandParam.ParamData[31*i];

                for (int j = 0; j < 30; j++)
                {
                    NameBuffer[j] = RecvCommandParam.ParamData[1 + 31*i+j];
                }

                cinterface.Name = Encoding.Default.GetString(NameBuffer);

                pos = cinterface.Name.IndexOf('\0');

                if (pos > 0)
                {
                    cinterface.Name = cinterface.Name.Substring(0, pos);
                }

                Logger.WriteRunLog("添加接口名称:" + cinterface.Name+"\tID:"+cinterface.ID);
                ltRet.Add(cinterface);
            }

            

            return ltRet;
        }

        public List<InterfaceMsg> GetMsgInfo(byte node)
        {
            List<InterfaceMsg> ltRet = new List<InterfaceMsg>();
            SendCommandParam = new PackageParam();
            SendCommandParam.ParamData[0] = 1;
            SendCommandParam.ParamData[1] = node;
            SendCommandParam.ParamLen = 2;
            RecvCommandParam = new PackageParam();
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_WALK_INTERMSG, SendCommandParam, RecvCommandParam);
            byte[] NameBuffer = new byte[RecvCommandParam.ParamLen - 1];
            int count = RecvCommandParam.ParamLen / 31;
            int pos;
            for (int i = 0; i < count; i++)
            {
                var cinterface = new InterfaceMsg();
                cinterface.ID = RecvCommandParam.ParamData[31 * i];
                for (int j = 0; j < 30; j++)
                {
                    NameBuffer[j] = RecvCommandParam.ParamData[1 + 31 * i + j];
                }

                cinterface.Name = Encoding.Default.GetString(NameBuffer);
                pos = cinterface.Name.IndexOf('\0');
                if (pos > 0)
                {
                    cinterface.Name = cinterface.Name.Substring(0, pos);
                }

                ltRet.Add(cinterface);
            }

            return ltRet;
        }
        public bool DoAction(byte nAction,byte[] actionpar,int paranlen)
        {
            string str=string.Empty;
            SendCommandParam = new PackageParam();
            SendCommandParam.ParamData[0] = nAction;
            SendCommandParam.ParamLen = (byte)(paranlen+1);
            for(int i=0;i<paranlen;i++)
            {
                SendCommandParam.ParamData[1 + i] = actionpar[i];
                str += actionpar[i].ToString()+" ";
            }

            RecvCommandParam = new PackageParam();
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_DO_ACTION, SendCommandParam, RecvCommandParam);
            return true;
        }

        public int Connect(string strComType,string Addr)
        {
            CommandDataPackage.BoardID = SlaveID;

            if(strComType=="Uart")
            return libcom.Connect(BoardID, 0, Addr);
            CType = ComType.Com_Net;
            return libcom.Connect(BoardID, 1, Addr);//网络连接
        }

        public int CloseCom()
        {         
            return libcom.CloseCom();
        }

        public bool SendCmd(byte Cmd)
        {
            SendCommandParam.ParamData[0] = 0;
            SendCommandParam.ParamLen = 0;
            return CommandDataPackage.SendDataPackage(BoardID, (ComCmd)Cmd, SendCommandParam, RecvCommandParam);
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        static extern uint GetTickCount();
        uint lastGetResult = 0;

        byte[] ActionReuslt=new byte[255];
        public byte[] QueryAllResult()
        {
            if ((GetTickCount() - lastGetResult) >100)
            {
                lastGetResult = GetTickCount();
                for (int i = 0; i < 255; i++)
                {
                    RecvCommandParam.ParamData[i] = 0;
                }

                if (!CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_RESULT, RecvCommandParam))
                {
                    return ActionReuslt;
                }

                for (int i = 0; i < 255; i++)
                {
                    ActionReuslt[i] = RecvCommandParam.ParamData[i];
                }
                
            }

            return ActionReuslt;
  
        }

        UInt32 ReadAllIO()
        {
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_SENSOR, RecvCommandParam);
            var AllSensorStatus = (UInt32)(RecvCommandParam.ParamData[0]) + (UInt32)(RecvCommandParam.ParamData[1] << 8) + (UInt32)(RecvCommandParam.ParamData[2] << 16) + (UInt32)(RecvCommandParam.ParamData[3] << 24);
            return AllSensorStatus;
        }

        public MCUDATA GetMCUData()
        {
           
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_MCU_DATA, RecvCommandParam);
            MCUDATA md = new MCUDATA();
         
            md.SM1POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 0);
            md.SM2POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 4);
            md.SM3POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 8);
            md.SM4POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 12);
            md.SM5POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 16);
            md.SM6POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 20);
            md.SM7POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 24);
            md.SM8POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 28);
            md.SM9POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 32);
            md.SM10POS = BitConverter.ToInt32(RecvCommandParam.ParamData,36);
            md.SM11POS = BitConverter.ToInt32(RecvCommandParam.ParamData,40);
            md.SM12POS = BitConverter.ToInt32(RecvCommandParam.ParamData, 44);
            return md;
        }

        public uint ReadSensor()
        {

            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_SENSOR, RecvCommandParam);
            var AllSensorStatus = (UInt32)(RecvCommandParam.ParamData[0]) + (UInt32)(RecvCommandParam.ParamData[1] << 8) + (UInt32)(RecvCommandParam.ParamData[2] << 16) + (UInt32)(RecvCommandParam.ParamData[3] << 24);
            return AllSensorStatus;
        }

        void SetIO(int id,bool ison)
        {
            byte[] buf = new byte[2];
            buf[0] = (byte)id;
            buf[1] = 3;
            if (ison)
            buf[1] = 1;

            for (byte i = 0; i < 2; i++)
            {
                SendCommandParam.ParamData[i] = buf[i];
            }
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_SET_DC_MOTOR, SendCommandParam);
        }

        public string QueryAllStep()
        {
            string strStepInfo = string.Empty;
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_STEP_INFO, RecvCommandParam);
            for (int i = 0; i < RecvCommandParam.ParamLen; i++)
            {
                strStepInfo += "Cmd"+(i+1).ToString("D2")+":"+RecvCommandParam.ParamData[i].ToString("X2") + "  ";
                if ((i % 10 == 9)&&(i>0))
                {
                    strStepInfo += "\r\n\r\n";
                }
            }

            return strStepInfo;
        }

        public void RunSM(int smid,int step,ushort speed)
        {
            byte[] cBuf = new byte[8];

            cBuf[0] = (byte)smid;
            if(step>0)
            {
                cBuf[1] = 1;    //正转
            }
            
            cBuf[2] = 0;
            cBuf[3] = (byte)(speed % 256);
            cBuf[4] = (byte)(speed / 256);
            cBuf[5] = (byte)(step % 256);
            cBuf[6] = (byte)(step / 256);
            for (byte i = 0; i < 7; i++)
            {
                SendCommandParam.ParamData[i] = cBuf[i];
            }
            CommandDataPackage.SendDataPackage(BoardID,ComCmd.CMD_SET_STEP_MOTOR, SendCommandParam);
        }

        public void StopSM(int smid)
        {
            byte[] cBuf = new byte[8];

            cBuf[0] = (byte)smid;
            cBuf[2] = 3;    //正转

       
            for (byte i = 0; i < 7; i++)
            {
                SendCommandParam.ParamData[i] = cBuf[i];
            }
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_SET_STEP_MOTOR, SendCommandParam);
        }
        public string QueryStepSeq(byte Cmd)
        {
            string strStepInfo = string.Empty;
            SendCommandParam.ParamData[0] = Cmd;
            SendCommandParam.ParamLen = 1;
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_STEP_SEQ, SendCommandParam, RecvCommandParam);
            STEPSEQ tLastStep = STEPSEQ.lSTEP_ERROR6;
            //if (RecvCommandParam.ParamLen != 87)
            //{
            //    return string.Empty;
            //}

            byte IsRun = RecvCommandParam.ParamData[82];
            ushort RunCnt = (ushort)(RecvCommandParam.ParamData[80] << 8);
            RunCnt += RecvCommandParam.ParamData[81];
            uint UseTime = (uint)(RecvCommandParam.ParamData[83] << 24);
            UseTime += (uint)(RecvCommandParam.ParamData[84] << 16);
            UseTime += (uint)(RecvCommandParam.ParamData[85] << 8);
            strStepInfo = "动作ID:" + Cmd + "\r\n";
            UseTime += (uint)(RecvCommandParam.ParamData[86]);
            if (IsRun == 1)
            {
                strStepInfo += "正在运行\t运行" + RunCnt.ToString() + "次\r\n函数调用序列:\r\n";
            }
            else
            {
                strStepInfo += "运行完成\t运行" + RunCnt.ToString() + "次\t耗时:" + UseTime.ToString() + "ms\r\n函数调用序列:\r\n";
            }

            if (RunCnt == 0)
            {
                return "动作还没执行!";
            }

            for (int i = 0; i < 40; i++)
            {
                if (RecvCommandParam.ParamData[i] == 0x50)
                {
                    break;
                }
                else
                {
                    var tEPSEQ = (STEPSEQ)RecvCommandParam.ParamData[i + 40];
                    var FunName = (LIB_CALL)RecvCommandParam.ParamData[i];
                    if (tEPSEQ != tLastStep)
                    {
                        strStepInfo += tEPSEQ.ToString() + ":\r\n";
                        tLastStep = tEPSEQ;
                    }
                    strStepInfo += FunName.ToString() + "\r\n";
                }
            }

            return strStepInfo;
        }

        public ushort QueryOneResult(byte Cmd)
        {
            var AllResult = QueryAllResult();
            ushort Ret = (ushort)(AllResult[2 * Cmd] + (ushort)(AllResult[2 * Cmd + 1] << 8));
            if ((Ret > 0) && (Ret != 0xff))
            {
                Thread.Sleep(50);
            }
            return Ret;
        }

        public string QueryErrorInfo(byte Cmd)
        {
            SendCommandParam.ParamData[0] = Cmd;
            SendCommandParam.ParamLen = 1;
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_ERROR_INFO, SendCommandParam, RecvCommandParam);
            return Encoding.Default.GetString(RecvCommandParam.ParamData,0,RecvCommandParam.ParamLen);
        }

        public bool ShareMem(byte[] SendData,int SendLen,ref byte[] RecvData,int RecvLen)
        {
    
            for(int i=0;i<SendLen;i++)
            {
                SendCommandParam.ParamData[i] = SendData[i];
            }
            SendCommandParam.ParamLen = (byte)SendLen;
            if(CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_SHARE_MEM_CMD, SendCommandParam, RecvCommandParam))
            {
                for(int i=0;i<RecvLen;i++)
                {
                    RecvData[i] = RecvCommandParam.ParamData[i];
                }

                return true;
            }
            return false;
        }

        public bool SharePC(byte[] SendData, int SendLen, ref byte[] RecvData, int RecvLen)
        {

            for (int i = 0; i < SendLen; i++)
            {
                SendCommandParam.ParamData[i] = SendData[i];
            }
            SendCommandParam.ParamLen = (byte)SendLen;
            if (CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_SHARE_PC, SendCommandParam, RecvCommandParam))
            {
                for (int i = 0; i < RecvLen; i++)
                {
                    RecvData[i] = RecvCommandParam.ParamData[i];
                }

                return true;
            }
            return false;
        }

        public byte[] QueryData()
        {
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_DATA,RecvCommandParam);
            return RecvCommandParam.ParamData;
        }

        public void  SetData(byte[] DataParam,byte nLen)
        {
            SendCommandParam.ParamLen = nLen;
            for (byte i = 0; i < nLen; i++)
            {
                SendCommandParam.ParamData[i] = DataParam[i];
            }
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_SET_DATA, SendCommandParam,RecvCommandParam);
        }

        public bool SendCmd(byte Cmd,byte[] ParanData,byte ParamLen)
        {
            for (byte i = 0; i < ParamLen; i++)
            {
                SendCommandParam.ParamData[i] = ParanData[i];
            }

            SendCommandParam.ParamLen = ParamLen;
            return CommandDataPackage.SendDataPackage(BoardID, (ComCmd)Cmd, SendCommandParam, RecvCommandParam);
        }

        public string GetVersion()
        {
            CommandDataPackage.SendDataPackage(BoardID, ComCmd.CMD_GET_VERSION,RecvCommandParam);
            byte[] VerBuffer = new byte[40];
            for (int i = 0; i < RecvCommandParam.ParamLen; i++)
            {
                VerBuffer[i] = RecvCommandParam.ParamData[i];
            }
            var ret = Encoding.Default.GetString(VerBuffer);
            return ret;

        }

        public byte IsActionOk(byte nID)
        {
            var AllResult = QueryAllResult();
            byte Ret = AllResult[2*nID];       
            return Ret;
        }

    }
}
